package rmmk.algorithms.features.global;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import rmmk.framework.datasources.Document;

/**
 * Klasa zliczająca globalnie wystąpienia wszystkich par słów we wszystkich
 * dokumentach
 * 
 * @author marcin
 * 
 */
public class PairsOfWordsGlobal {

	Logger logger = LoggerFactory.getLogger(PairsOfWordsGlobal.class);
	private static HashMap<String, Integer> pairOfWords = new HashMap<>();
	private boolean removeCommonPairs = true;

	public void calculate(List<Document> documents) {

		pairOfWords.clear();

		for (Document doc : documents) {
			for (int i = 0; i < doc.getExtractedWords().size() - 1; ++i) {
				this.checkIfContainsAndAdd(doc.getExtractedWords().get(i), doc
						.getExtractedWords().get(i + 1));
			}
		}

		int max = 0;

		for (Entry<String, Integer> e : pairOfWords.entrySet())
			if (e.getValue() > max)
				max = e.getValue();

		logger.info("Ilość zliczonych par słów: " + pairOfWords.size());
		logger.info("Maksymalna częstość wystąpień pary słów: " + max);

		int limitTop = max - (max / 4);
		int limitBottom = (max / 8);

		/*
		 * for (Entry<String, Integer> e : pairOfWords.entrySet()) if
		 * (e.getValue() < limit) pairOfWords.remove(e.getKey());
		 */

		if (removeCommonPairs) {
			Iterator<Entry<String, Integer>> iter = pairOfWords.entrySet()
					.iterator();
			while (iter.hasNext()) {
				Entry<String, Integer> e = iter.next();
				if (e.getValue() > limitTop || e.getValue() < limitBottom)
					iter.remove();
			}

			logger.info("Ilość par słów w bazie po odrzuceniu części: "
					+ pairOfWords.size());
		}
	}

	private void checkIfContainsAndAdd(String a, String b) {
		if (pairOfWords.containsKey(a + b) || pairOfWords.containsKey(b + a)) {
			if (pairOfWords.containsKey(a + b)) {
				Integer ab = pairOfWords.get(a + b);
				pairOfWords.put(a + b, ++ab);
			} else {
				Integer ba = pairOfWords.get(b + a);
				pairOfWords.put(b + a, ++ba);
			}
		} else {
			pairOfWords.put(a + b, 0);
		}
	}

	public int getFeatureSize() {
		return pairOfWords.size();
	}

	@SuppressWarnings("unchecked")
	public static HashMap<String, Integer> getNBiggest(int n) {
		HashMap<String, Integer> map = (HashMap<String, Integer>) pairOfWords
				.clone();

		HashMap<String, Integer> finalMap = new HashMap<>();

		Entry<String, Integer> entry;

		while (finalMap.size() < n) {
			Iterator<Entry<String, Integer>> ie = map.entrySet().iterator();
			if (ie.hasNext()) {
				entry = ie.next();
				while (ie.hasNext()) {
					Entry<String, Integer> temp = ie.next();
					if (entry.getValue() < temp.getValue())
						entry = temp;
				}
				finalMap.put(entry.getKey(), entry.getValue());
				map.remove(entry.getKey());
			} else
				break;
		}

		return finalMap;
	}

	public boolean isRemoveCommonPairs() {
		return removeCommonPairs;
	}

	public void setRemoveCommonPairs(boolean removeCommonPairs) {
		this.removeCommonPairs = removeCommonPairs;
	}
}
